package com.iemp.security;

import com.iemp.config.consts.ApiConsts;
import com.iemp.filter.JWTAuthenticationFilter;
import com.iemp.filter.JWTAuthorizationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


@Configuration
@EnableWebSecurity
@PropertySource("classpath:securitySettings.properties")
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    private final UserDetailsService userDetailsService;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;
    private final AccessDeniedHandler accessDeniedHandler;

    @Value("${password.encode.salt}")
    private final String salt = null;

    @Value("${token.expire.access}")
    private final Integer accessTokenExpirePeriod = null;

    @Value("${token.expire.refresh}")
    private final Integer refreshTokenExpirePeriod = null;

    @Value("${login.url}")
    private final String loginUrl = null;

    public SecurityConfig(@Qualifier("accountServiceImpl") UserDetailsService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder, AccessDeniedHandler accessDeniedHandler) {
        this.userDetailsService = userDetailsService;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
        this.accessDeniedHandler = accessDeniedHandler;

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
    }



    @Override
    protected void configure(HttpSecurity http) throws Exception {

        JWTAuthenticationFilter jwtAuthenticationFilter =
                new JWTAuthenticationFilter(salt, authenticationManagerBean(), accessTokenExpirePeriod, refreshTokenExpirePeriod);

        http.formLogin().loginPage(ApiConsts.LOGIN_PAGE);

        log.info("salt:{}", salt);

        /* 设置 验证过滤器 要处理的URL */
        jwtAuthenticationFilter.setFilterProcessesUrl(loginUrl);

        /* 关闭 CSRF 和 CORS, 更改 Session 创建策略 */
        http.cors().disable();
        http.csrf().disable();
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        /* 授权 */
        // 所有人都有权限登录
//        http.authorizeRequests().antMatchers("/**").permitAll();
        http.authorizeRequests().antMatchers("" + "/**").permitAll();
//        http.authorizeRequests().antMatchers(loginUrl + "/**").permitAll();
//        http.authorizeRequests().antMatchers("news/**").hasAnyAuthority(RoleConsts.ROLE_MANAGER);
//        http.authorizeRequests().antMatchers("/**").hasAnyAuthority(RoleConsts.ROLE_SUPER_ADMIN);
//        http.authorizeRequests().anyRequest().authenticated();

        /* 403 Forbiden 处理 */
        // AuthenticationEntryPoint 用来解决匿名用户访问无权限资源时的异常
        // AccessDeineHandler 用来解决认证过的用户访问无权限资源时的异常
        http.exceptionHandling().accessDeniedHandler(accessDeniedHandler);

        /* 装配验证过滤器和授权过滤器 */
        http.addFilter(jwtAuthenticationFilter);
        http.addFilterBefore(new JWTAuthorizationFilter(salt, loginUrl), UsernamePasswordAuthenticationFilter.class);
    }
    //
    //    @Bean
    //    @Override
    //    public AuthenticationManager authenticationManagerBean() throws Exception {
    //        return super.authenticationManagerBean();
    //    }
}
